package com.czh.mock.result;

import com.alibaba.fastjson.JSON;
import com.czh.mock.constant.MockFileConstant;
import com.czh.mock.exceptions.FileException;
import com.czh.mock.exceptions.code.MockCodeEnum;
import com.czh.mock.result.config.ResultConfig;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.function.Function;

/**
 * 以json格式保存mock数据
 * 一个json文件保存的应该是一个完整的json，数据量大的时候分批保存需要将每批数据保存到一个单独的json文件
 * 所以需要定义一个目录，用于保存多批json文件
 *
 * @author manem
 */
public class MockResultJson extends AbstractMockResult{
    /**
     *  保存多批json文件的目录
     */
    private String batchPath = "";
    public MockResultJson(ResultConfig config) {
        this.config = config;
    }

    @Override
    public <T, R> MockResultJson mockField(String field, T param, Function<T, R> mockAlgorithm) {
        super.mockField(field, param, mockAlgorithm);
        return this;
    }

    @Override
    String getPath() {
        if (StringUtils.isBlank(this.batchPath)) {
            this.batchPath = MockFileConstant.MOCK_FILE_JSON_PATH + RandomStringUtils.randomAlphanumeric(10) + File.separator;
        }
        return this.batchPath;
    }

    @Override
    String getFileSuffix() {
        return ".json";
    }

    @Override
    void write(List<List<MockFieldSegment>> mockRowList, boolean close) {
        // 通过Jackson将mockRowList序列化成json字符串
        try {
            String json = JSON.toJSONString(mockRowList);
            // 重新设置文件名
            this.getConfig().setFilename(RandomStringUtils.randomAlphanumeric(10));
            // 每次写入都使用新的文件流
            this.getOutputStream(true).write(json.getBytes());
            // 每次写入都刷新文件流
            this.getOutputStream(false).flush();
            // 关闭文件流
            this.getOutputStream(false).close();
        }  catch (IOException e) {
            logger.error("json数据写入文件失败", e);
            throw new FileException(MockCodeEnum.FILE_WRITE_ERROR);
        }
    }

    @Override
    public String getOutputResultPath() {
        return this.getPath();
    }
}
